﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using UpdaterForm.Annotations;
using UpdaterForm.Utils;

namespace UpdaterForm.Tabs
{
    /// <summary>
    ///     Interaction logic for AppControlNew.xaml
    /// </summary>
    public partial class AppInstance : INotifyPropertyChanged
    {
        private readonly AppData _app;
        private readonly BackgroundWorker _worker;
        private Update _selectedUpdate;
        private ObservableCollection<Update> _updates;

        public AppInstance(AppData app)
        {
            _app = app;
            _worker = new BackgroundWorker();
            _worker.DoWork += Apply;
            _worker.RunWorkerCompleted += Complete;
            InitializeComponent();
            LoadUpdates(_app);
        }

        public ObservableCollection<Update> Updates
        {
            get
            {
                if (_updates == null)
                    _updates = new ObservableCollection<Update>();

                return _updates;
            }
            set { _updates = value; }
        }

        public ICollection<Update> SelectedUpdates { get; set; }

        public Update SelectedUpdate
        {
            get { return _selectedUpdate; }
            set
            {
                _selectedUpdate = value;
                OnPropertyChanged("SelectedUpdate");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void Complete(object sender, RunWorkerCompletedEventArgs e)
        {
            Dispatcher.Invoke((Action) (() => { ProcessPrb.Visibility = Visibility.Collapsed; }));
        }

        private void Apply(object sender, DoWorkEventArgs e)
        {
            Dispatcher.Invoke((Action) (() => { ProcessPrb.Visibility = Visibility.Visible; }));

            foreach (Update update in SelectedUpdates)
            {

                update.Install();
                SetCurrentVersion(update);
            }
        }

        private void SetCurrentVersion(Update update)
        {
            if (update.Log.State.Equals(UpdateState.InstallFailed))
            {
                return;
            }
            if (!update.Custom)
            {
                foreach (Update up in Updates)
                {
                    if (up.IsInstalled.Equals(UpdateState.CurrentVesion))
                    {
                        up.IsInstalled = UpdateState.FullyInstalled;
                        break;
                    }
                }
                update.IsInstalled = UpdateState.CurrentVesion;
                _app.CurrentVersion = update.UpdateData.DateName;
            }
        }

        private void LoadUpdates(AppData app)
        {
            Updates.Clear();
            string updatesForldser = Settings.Instance.RepositoryPath;
            foreach (DirectoryInfo dir in DirectoryUtil.GetDirs(new DirectoryInfo(updatesForldser)))
            {
                string appUpdate = Path.Combine(dir.FullName, app.AppName);
                if (!Directory.Exists(appUpdate))
                    continue;

                var updateDir = new DirectoryInfo(appUpdate);
                var update = new Update(updateDir, app);
                Updates.Add(update);
            }
        }

        private void ApplyBtn_Click(object sender, RoutedEventArgs e)
        {
            if (!_worker.IsBusy)
                _worker.RunWorkerAsync();
        }


        private void RefreshBtn_Click(object sender, RoutedEventArgs e)
        {
            LoadUpdates(_app);
        }

        private void UpdateDirsList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var source = sender as ListView;
            if (source != null)
                SelectedUpdates = source.SelectedItems.Cast<Update>().ToList();
        }

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}